<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
      "\u0061"
// "a"

//这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符，必须用两个双字节的形式表示。

"\uD842\uDFB7"
// "𠮷"

"\u20BB7"  //7
"\u{20BB7}"
// "𠮷"

"\u{41}\u{42}\u{43}"
// "ABC"

let hello = 123;
hell\u{6F} // 123
//只要将码点放入大括号，就能正确解读该字符。
'\u{1F680}' === '\uD83D\uDE80'
// true

//表示字符的六种方法
'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true
//2字符串遍历
for (let codePoint of 'foo') {
  console.log(codePoint)
}
// "f"
// "o"
// "o"
//这个遍历器最大的优点是可以识别大于0xFFFF的码点，传统的for循环无法识别这样的码点。
    
let text = String.fromCodePoint(0x20BB7);

for (let i = 0; i < text.length; i++) {
  console.log(text[i]);
}
// " "
// " "

for (let i of text) {
  console.log(i);
}
// "𠮷"

//字符串text只有一个字符，但是for循环会认为它包含两个字符（都不可打印），而for...of循环会正确识别出这一个字符。
    //3.格式
    // JavaScript 规定有5个字符，不能在字符串里面直接使用，只能使用转义形式。

    // U+005C：反斜杠（reverse solidus)
    // U+000D：回车（carriage return）
    // U+2028：行分隔符（line separator）
    // U+2029：段分隔符（paragraph separator）
    // U+000A：换行符（line feed）
    //字符串里面不能直接包含反斜杠，一定要转义写成\\或者\u005c
    const PS = eval("'\u2029'");
// 注意，模板字符串现在就允许直接输入这两个字符。另外，
// 正则表达式依然不允许直接输入这两个字符，这是没有问题的，因为 JSON 本来就不允许直接包含正则表达式。
   //4.json.stringify
   //0xD800到0xDFFF之间的码点，不能单独使用，
//    必须配对使用。比如，\uD834\uDF06是两个码点，
//    但是必须放在一起配对使用，代表字符𝌆。
//    这是为了表示码点大于0xFFFF的字符的一种变通方法。
//    单独使用\uD834和\uDF06这两个码点是不合法的，
//    或者颠倒顺序也不行，因为\uDF06\uD834并没有对应的字符。
//JSON.stringify()的问题在于，它可能返回0xD800到0xDFFF之间的单个码点。

JSON.stringify('\u{D834}') // "\u{D834}"
// 如果遇到0xD800到0xDFFF之间的单个码点，
// 或者不存在的配对形式，它会返回转义字符串，
// 留给应用自己决定下一步的处理。

JSON.stringify('\u{D834}') // ""\\uD834""
JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""
//5模板字符串
$('#result').append(
  'There are <b>' + basket.count + '</b> ' +
  'items in your basket, ' +
  '<em>' + basket.onSale +
  '</em> are on sale!'
);

$('#result').append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${basket.onSale}</em>
  are on sale!
`);
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
   
$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`);//.trim()方法消除换行
function authorize(user, action) {
  if (!user.hasPrivilege(action)) {
    throw new Error(
      // 传统写法为
      // 'User '
      // + user.name
      // + ' is not authorized to do '
      // + action
      // + '.'
      `User ${user.name} is not authorized to do ${action}.`);
  }
}
//模板字符串之中还能调用函数。

function fn() {
  return "Hello World";
}

`foo ${fn()} bar`
// foo Hello World bar

//模板字符串甚至还能嵌套。

const tmpl = addrs => `
  <table>
  ${addrs.map(addr => `
    <tr><td>${addr.first}</td></tr>
    <tr><td>${addr.last}</td></tr>
  `).join('')}
  </table>
`;
//生成正式模板的实例。

let template = `
<ul>
  <% for(let i=0; i < data.supplies.length; i++) { %>
    <li><%= data.supplies[i] %></li>
  <% } %>
</ul>
`;
echo('<ul>');
for(let i=0; i < data.supplies.length; i++) {
  echo('<li>');
  echo(data.supplies[i]);
  echo('</li>');
};
echo('</ul>');

//7
alert`hello`
// 等同于
alert(['hello'])
tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
tag函数实际上以下面的形式调用。

tag(['Hello ', ' world ', ''], 15, 50)

//下面是tag函数的一种写法

let a = 5;
let b = 10;

function tag(s, v1, v2) {
  console.log(s[0]);
  console.log(s[1]);
  console.log(s[2]);
  console.log(v1);
  console.log(v2);

  return "OK";
}

tag`Hello ${ a + b } world ${ a * b}`;
// "Hello "
// " world "
// ""
// 15
// 50
// "OK"


   </script>
</body>
</html>